package com.contest.ws;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.contest.entity.*;
import com.contest.service.*;
import com.contest.util.DateUtil;
import com.contest.util.IdWorker;
import com.contest.util.WsNeed;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.datetime.DateFormatter;
import org.springframework.web.socket.*;
import org.springframework.web.socket.WebSocketHandler;

import java.math.BigDecimal;
import java.util.*;

public class WsChatWebSocketHandler implements WebSocketHandler {

    @Autowired
    private BettingRecordService bettingRecordService;
    @Autowired
    GameInfoService gameInfoService;
    @Autowired
    RaceInfoService raceInfoService;
    @Autowired
    ClanInfoService clanInfoService;
    @Autowired
    UserInfoService userInfoService;
    @Autowired
    RoomInfoService roomInfoService;
    @Autowired
    IdWorker idWorker;

    private ObjectMapper json = new ObjectMapper();

    private final static WebSocketSessionManager socketSessionManager = WebSocketSessionManager.getInstance();

    /**
     * 建立链接后执行
     *
     * @param webSocketSession
     * @throws Exception
     */
    public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
        WsNeed wsNeed = WsNeed.getInstance();
        bettingRecordService = wsNeed.getBettingRecordService();
        gameInfoService = wsNeed.getGameInfoService();
        raceInfoService = wsNeed.getRaceInfoService();
        roomInfoService = wsNeed.getRoomInfoService();
        clanInfoService = wsNeed.getClanInfoService();
        userInfoService = wsNeed.getUserInfoService();
        idWorker = wsNeed.getIdWorker();
        String roomId = webSocketSession.getAttributes().get("roomId").toString();
        String raceId = webSocketSession.getAttributes().get("raceId").toString();
        Map<String, Map<String, List<WebSocketSession>>> sessionMap = socketSessionManager.getSessionMap();
        if (sessionMap == null) {
            sessionMap = Collections.synchronizedMap(new HashMap<String, Map<String, List<WebSocketSession>>>());
            socketSessionManager.setSessionMap(sessionMap);
        }
        Map<String, List<WebSocketSession>> roomSession = sessionMap.get(raceId);
        if (roomSession == null) {
            roomSession = Collections.synchronizedMap(new HashMap<String, List<WebSocketSession>>());
            sessionMap.put(raceId, roomSession);
        }
        List<WebSocketSession> sessions = roomSession.get(roomId);
        if (sessions == null) {
            sessions = Collections.synchronizedList(new ArrayList<WebSocketSession>());
            sessions.add(webSocketSession);
            roomSession.put(roomId, sessions);
        } else {
            sessions.add(webSocketSession);
        }

    }

    /**
     * 消息处理
     *
     * @param webSocketSession
     * @param webSocketMessage
     * @throws Exception
     */
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
        WsUser wsUser = json.readValue(webSocketMessage.getPayload().toString(), WsUser.class);
        String msgType = wsUser.getMsgType();
        String raceId = wsUser.getRaceId();
        String roomId = wsUser.getRoomId();
        String roomName = wsUser.getRoomName();
        String userId = wsUser.getUserId();
        String clanId = wsUser.getClanId();
        String clanName = wsUser.getClanName();
        String userName = wsUser.getUserName();
        float amount = wsUser.getAmount();
        String content = wsUser.getContent();
        String bettingNum = wsUser.getBettingNum();
        String result = null;
        Map<String, Map<String, List<WebSocketSession>>> sessionMap = socketSessionManager.getSessionMap();
        List<WebSocketSession> socketSessions = sessionMap.get(raceId).get(roomId);
        for (WebSocketSession session : socketSessions) {
            if (session.isOpen()) {
                if ("-1".equals(msgType) || "".equals(msgType)) {
                    session.sendMessage(new TextMessage(json.writeValueAsString(wsUser)));
                } else if ("0".equals(msgType)) {
                    //单场胜负
                    result = betting(amount, 0, clanId, userId, raceId, roomId, roomName, content, bettingNum);
                } else if ("1".equals(msgType)) {
                    //大小单双
                    result = betting(amount, 1, clanId, userId, raceId, roomId, roomName, content, bettingNum);
                } else if ("2".equals(msgType)) {
                    //总场胜负
                    result = betting(amount, 2, clanId, userId, raceId, roomId, roomName, content, bettingNum);
                } else if ("3".equals(msgType)) {
                    //特码
                    result = betting(amount, 3, clanId, userId, raceId, roomId, roomName, content, bettingNum);
                }
                if (result != null && "0".equals(result)) {
                    wsUser.setResultType(1);
                    wsUser.setContent("投注战队：&nbsp;"+clanName+"&nbsp;<br>"+"金币：<span style='color:red'>"+amount+"<span>");
                    session.sendMessage(new TextMessage(json.writeValueAsString(wsUser)));
                } else if(result != null && "1".equals(result)) {
                    wsUser.setResultType(1);
                    wsUser.setContent("投注号码：&nbsp;"+bettingNum+"&nbsp;<br>"+"金币：<span style='color:red'>"+amount+"<span>");
                    session.sendMessage(new TextMessage(json.writeValueAsString(wsUser)));
                }else if(result != null && "2".equals(result)) {
                    wsUser.setResultType(1);
                    wsUser.setContent("投注战队：&nbsp;"+clanName+"&nbsp;<br>"+"金币：<span style='color:red'>"+amount+"<span>");
                    session.sendMessage(new TextMessage(json.writeValueAsString(wsUser)));
                }else if(result != null && "3".equals(result)) {
                    wsUser.setResultType(1);
                    wsUser.setContent("投注号码&nbsp;"+bettingNum+"&nbsp;<br>"+"金币：<span style='color:red'>"+amount+"<span>");
                    session.sendMessage(new TextMessage(json.writeValueAsString(wsUser)));
                }else if(result != null && "-1".equals(result)) {
                    wsUser.setResultType(0);
                    wsUser.setContent("下注失败");
                    session.sendMessage(new TextMessage(json.writeValueAsString(wsUser)));
                }
            }
        }
    }

    /**
     * 错误处理
     *
     * @param webSocketSession
     * @param throwable
     * @throws Exception
     */
    public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
        if (webSocketSession.isOpen()) {
            webSocketSession.close();
        }
    }

    /**
     * 连接关闭处理
     *
     * @param webSocketSession
     * @param closeStatus
     * @throws Exception
     */
    public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
        String raceId = webSocketSession.getAttributes().get("raceId").toString();
        String roomId = webSocketSession.getAttributes().get("roomId").toString();
        socketSessionManager.getSessionMap().get(raceId).get(roomId).remove(webSocketSession);
        if (webSocketSession.isOpen()) {
            webSocketSession.close();
        }
    }

    private String betting(float amount, int type, String clanId, String userId, String raceId, String roomId, String roomName, String content, String bettingNum) {
        RaceInfo raceInfo = raceInfoService.selectById(raceId);
        GameInfo gameInfo = gameInfoService.selectById(raceInfo.getFdGameId());
        UserInfo userInfo = userInfoService.selectById(userId);
        float over = userInfo.getFdOver().floatValue();
        if (over > amount) {
            userInfo.setFdOver(BigDecimal.valueOf(over - amount));
            userInfoService.updateById(userInfo);
            BettingRecord bettingRecord = new BettingRecord();
            bettingRecord.setFdId(idWorker.nextId() + "");
            bettingRecord.setFdType(type);
            bettingRecord.setFdBettingTime(DateUtil.now());
            bettingRecord.setFdRoomId(roomId);
            bettingRecord.setFdRoomName(roomName);
            bettingRecord.setFdGameId(gameInfo.getFdId());
            bettingRecord.setFdGameName(gameInfo.getFdName());
            bettingRecord.setFdRaceId(raceId);
            bettingRecord.setFdRaceName(raceInfo.getFdName());
            bettingRecord.setFdBettingAmount(BigDecimal.valueOf(amount));
            if (clanId != null && !"".equals(clanId)) {
                ClanInfo clanInfo = clanInfoService.selectById(clanId);
                bettingRecord.setFdBettingWarId(clanId);
                bettingRecord.setFdBettingWarName(clanInfo.getFdName());
            }
            bettingRecord.setFdUserId(userId);
            bettingRecord.setFdUserName(userInfo.getFdNickname());
            bettingRecord.setFdBettingNum(bettingNum);
            bettingRecord.setFdResult(0);
            bettingRecord.setFdIsSettlement(0);
            bettingRecord.setFdRemark(content);
            bettingRecordService.insert(bettingRecord);
            return type+"";
        } else {
            return "-1";
        }
    }

    public boolean supportsPartialMessages() {
        return false;
    }

}
